package com.andy.drools.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.Message;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.utils.KieHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;

import com.andy.drools.model.Rule;
import com.andy.drools.model.RuleConfig;
import com.andy.drools.model.vo.RuleVo;
import com.andy.drools.service.RuleConfigService;

/**
 * 
 * @Description:
 * @author: Andy
 * @date: 2020年7月6日 下午4:29:15
 */
public class DroolsUtils {

	public static KieContainer kieContainer;
	public static Map<String, KieContainer> kieContainerMap;

	@Autowired
	private static RuleConfigService ruleConfigService;

	public static void init() {
		if (ruleConfigService == null) {
			ruleConfigService=SpringUtils.getBean(RuleConfigService.class);

//			ruleConfigService = (RuleConfigService) ContextLoader.getCurrentWebApplicationContext()
//					.getBean(RuleConfigService.class);
		}
	}

	/**
	 * 
	 * @Description:这个用于多套规则时，直接通过key来获取
	 * @param key
	 * @return
	 */
	public static KieContainer getKieContainerMapByKey(String key) {
		return kieContainerMap.get(key);
	}

	/**
	 * 
	 * @Description:这个用于一套规则时，需要通过这个来获取
	 * @return
	 */
	public static KieContainer getKieContainer() {
		return kieContainer;
	}

	/**
	 * 
	 * @Description:用于重新加载规则
	 * @param ruleType 1--一套规则，2--多套规则
	 * @return
	 */
	public static String reload(String ruleType) {
		try {
			if ("1".equals(ruleType)) {
				KieContainer newKieContainer = loadContainerFromString(loadSingleRules());
				kieContainer = newKieContainer;
			} else {
				kieContainerMap = getMapKieContainer();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return "更新规则失败...";
		}
		return "更新规则成功";
	}

	private static List<RuleVo> loadSingleRules() {
		// 查找数据库对应的规则库，不进行规则分类的加载
		init();
		List<RuleVo> ruleVos = ruleConfigService.selectRuleVoList(null);
		return ruleVos;
	}

	private static KieContainer loadContainerFromString(List<RuleVo> rules) {
		long startTime = System.currentTimeMillis();
		KieServices ks = KieServices.Factory.get();
		KieRepository kr = ks.getRepository();
		KieFileSystem kfs = ks.newKieFileSystem();

		for (Rule rule : rules) {
			String drl = rule.getContent();
			kfs.write("src/main/resources/" + drl.hashCode() + ".drl", drl);
		}

		KieBuilder kb = ks.newKieBuilder(kfs);

		kb.buildAll();
		if (kb.getResults().hasMessages(Message.Level.ERROR)) {
			throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());
		}
		long endTime = System.currentTimeMillis();
		System.out.println("Time to build rules : " + (endTime - startTime) + " ms");
		startTime = System.currentTimeMillis();
		KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
		endTime = System.currentTimeMillis();
		System.out.println("Time to load container: " + (endTime - startTime) + " ms");
		return kContainer;
	}

	private static List<RuleVo> loadManyRules() {
		// 查找数据库对应的规则库，进行加载
		List<RuleConfig> ruleConfigs = ruleConfigService.selectRuleConfigList(null);
		List<RuleVo> ruleVos = null;
		for (RuleConfig ruleConfig : ruleConfigs) {
			RuleVo ruleVo = new RuleVo();
			ruleVo.setForeignKey(ruleConfig.getRuleKey());
			ruleVos = ruleConfigService.selectRuleVoList(ruleVo);
		}
		return ruleVos;
	}

	public static Map<String, KieContainer> getMapKieContainer() throws IOException {
		long startTime = System.currentTimeMillis();
		Map<String, KieContainer> kieContainerMap = new HashMap<String, KieContainer>();
		// 查找数据库对应的规则库，进行加载
		List<RuleConfig> ruleConfigs = ruleConfigService.selectRuleConfigList(null);

		for (RuleConfig ruleConfig : ruleConfigs) {
			RuleVo ruleVo = new RuleVo();
			ruleVo.setForeignKey(ruleConfig.getRuleKey());
			List<RuleVo> ruleVos = ruleConfigService.selectRuleVoList(ruleVo);

			KieServices ks = KieServices.Factory.get();
			KieRepository kr = ks.getRepository();
			KieFileSystem kieFileSystem = ks.newKieFileSystem();
			for (RuleVo rule : ruleVos) {
				String drl = rule.getContent();
				kieFileSystem.write("src/main/resources/" + drl.hashCode() + ".drl", drl);
			}

			KieBuilder kb = ks.newKieBuilder(kieFileSystem);

			kb.buildAll();
			if (kb.getResults().hasMessages(Message.Level.ERROR)) {
				throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());
			}
			long endTime = System.currentTimeMillis();
//			System.out.println("Time to build rules : " + (endTime - startTime) + " ms");
			startTime = System.currentTimeMillis();
			KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
			endTime = System.currentTimeMillis();
//			System.out.println("Time to load container: " + (endTime - startTime) + " ms");
			kieContainerMap.put(ruleConfig.getRuleKey(), kContainer);
		}
		return kieContainerMap;
	}
	
	
//	public void handle() {
//		Rule ruleHandle = new Rule();
//		KieHelper helper = new KieHelper();
//		helper.addContent(rule2Drl(null), ResourceType.DRL);
//		KieSession kSession = helper.build().newKieSession();
//		kSession.insert(new Object());
//		kSession.fireAllRules();
//		kSession.dispose();
//	}
//
//	public String rule2Drl(Rule rule) {
//		StringBuilder result = new StringBuilder();
//		/* package部分 */
//		result.append("package rule1;\r\n");
//		result.append("\r\n");
//
//		/* 导包部分 */
//		result.append("import com.winning.rules.engine.model.Fact;\r\n");
//		result.append("import com.winning.rules.engine.model.FactProperty;\r\n");
//		result.append("import java.util.List;\r\n");
//		result.append("\r\n");
//
//		/* 规则申明部分 */
//		result.append("rule \"32353242\"\r\n");
//
//		/* 规则属性部分 */
//
//		/* 规则条件部分 */
//		result.append("\twhen\r\n");
//		result.append("\t\teval(true)\r\n");
//
//		/* 规则结果部分 */
//		result.append("\tthen\r\n");
//		result.append("\t\tSystem.out.println(\"动态加载的规则被触发了\");\r\n");
//
//		/* 规则结束 */
//		result.append("end\r\n");
//		return result.toString();
//	}

}
